"""
Token相关服务模块

该模块包含与用户认证和Token管理相关的服务函数。
"""


from fastapi import HTTPException, status

from app.core.handlers.auth import (
    create_access_token,
    create_refresh_token,
    decode_token,
)
from app.core.handlers.database import SessionDep
from app.core.handlers.response import SuccessResponse
from app.user.models.user import User, UserLogin


class TokenService:
    """Token服务类"""

    def __init__(self, db: SessionDep) -> None:
        """
        初始化TokenService

        Args:
            db: 数据库会话依赖
        """
        self.db = db

    async def login(self, form_data: UserLogin):
        """
        用户登录服务实现

        Args:
            form_data: 用户登录表单数据

        Returns:
            登录结果响应字典
        """
        return await self._authenticate_and_generate_tokens(
            form_data.username, form_data.password
        )

    async def refresh_token(self, refresh_token: str):
        """
        刷新令牌服务实现

        Args:
            refresh_token: 刷新令牌

        Returns:
            新的访问令牌和刷新令牌响应字典
        """
        # 解码刷新令牌
        payload = decode_token(refresh_token)
        if not payload:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED, detail="无效的刷新令牌"
            )

        # 获取用户ID
        user_id = payload.get("sub")
        if not user_id:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED, detail="刷新令牌格式错误"
            )

        # 直接使用用户ID生成新的令牌，无需查询用户
        return await self._generate_tokens_for_user_by_id(user_id)

    async def _authenticate_and_generate_tokens(self, username: str, password: str):
        """
        验证用户凭据并生成令牌

        Args:
            username: 用户名
            password: 密码

        Returns:
            令牌响应字典
        """
        user_query = self.db.select(User, skip_permission_check=True).where(
            User.username == username
        )
        user = self.db.scalar(user_query)
        if not user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, detail="用户不存在"
            )
        pass_verified = user.verify_password(password)
        if not pass_verified:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED, detail="密码错误"
            )

        return await self._generate_tokens_for_user(user)

    async def _generate_tokens_for_user(self, user: User):
        """
        为用户对象生成访问令牌和刷新令牌

        Args:
            user: 用户对象

        Returns:
            令牌响应字典
        """
        return await self._generate_tokens_for_user_by_id(str(user.id))

    @staticmethod
    async def _generate_tokens_for_user_by_id(user_id: str):
        """
        根据用户ID生成访问令牌和刷新令牌

        Args:
            user_id: 用户ID

        Returns:
            令牌响应字典
        """
        access_token = create_access_token(subject=user_id)
        refresh_token = create_refresh_token(subject=user_id)
        return SuccessResponse(
            data={"access_token": access_token, "refresh_token": refresh_token}
        )
